/**
 * @file    drv_spi.c
 * @brief 	spi驱动-软件模拟
 * @author  Liu wei
 * @version 1.0.1
 * @date    2023-04-18
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-04-18 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */
/* includes ------------------------------------------------------------------*/
#include "drv_spi.h"
#include "drv_gpio.h"
#include "drv_gpio_pcfg.h"
/* macro/define --------------------------------------------------------------*/

/* typedef -------------------------------------------------------------------*/
#define SPI_TIMEOUT          (255)
/* local functions -----------------------------------------------------------*/
static void drv_spi_set_cs_low(void);
static void drv_spi_soft_send_byte(uint8_t byte);
static uint8_t drv_spi_soft_send_read_byte(uint8_t s_byte);
/* static variables ----------------------------------------------------------*/

/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
/**
 * @brief    SPI底层驱动初始化
 * @param    
 * @return
*/
void drv_spi_init(uint8_t spi_id)
{
	drv_spi_soft_init();
//	
//	if(spi_id == DRV_SPI2)
//	{
//		SYS_UnlockReg();
//		
//		CLK_SetModuleClock(SPI2_MODULE, CLK_CLKSEL2_SPI2SEL_PCLK1, MODULE_NoMsk);
//		
//		CLK_EnableModuleClock(SPI2_MODULE);
//		
//		/* Setup SPI2 multi-function pins */                                               
//		SYS->GPA_MFPH |= SYS_GPA_MFPH_PA15MFP_SPI2_MOSI | SYS_GPA_MFPH_PA14MFP_SPI2_MISO | SYS_GPA_MFPH_PA13MFP_SPI2_CLK | SYS_GPA_MFPH_PA12MFP_SPI2_SS;

//		/* Enable SPI2 clock pin (PA13) schmitt trigger */
//		PA->SMTEN |= GPIO_SMTEN_SMTEN13_Msk;

//		/* Enable SPI2 I/O high slew rate */
//		GPIO_SetSlewCtl(PA, 0xF000, GPIO_SLEWCTL_HIGH);
//		
//		SPI_Open(SPI2, SPI_MASTER, SPI_MODE_3, 8, 1000000);
//		
//		SPI_DisableAutoSS(SPI2);

//		SYS_LockReg();
//	}
}

void drv_spi_soft_init(void)
{
	drv_gpio_cfg_mode(AFE_SPI_CLK_PORT , AFE_SPI_CLK_PIN ,GPIO_MODE_OUTPUT);
	drv_gpio_cfg_mode(AFE_SPI_MISO_PORT , AFE_SPI_MISO_PIN ,GPIO_MODE_INPUT);
	drv_gpio_cfg_mode(AFE_SPI_MOSI_PORT , AFE_SPI_MOSI_PIN ,GPIO_MODE_OUTPUT);
	drv_gpio_cfg_mode(AFE_SPI_CS_PORT , AFE_SPI_CS_PIN ,GPIO_MODE_OUTPUT);
	
	GPIO_SetPullCtl(AFE_SPI_CLK_PORT ,AFE_SPI_CLK_PIN , GPIO_PUSEL_PULL_UP);
	GPIO_SetPullCtl(AFE_SPI_MISO_PORT ,AFE_SPI_MISO_PIN , GPIO_PUSEL_PULL_UP);
	GPIO_SetPullCtl(AFE_SPI_MOSI_PORT ,AFE_SPI_MOSI_PIN , GPIO_PUSEL_PULL_UP);
}

/**
 * @brief  SPI读写一个字符
 * @param  spi_id : SPI 接口
 * @param  wbyte :写值
 * @param  rbyte :读值
 * @return void
 */
uint8_t drv_spi_write_read_byte(uint8_t spi_id , uint8_t wbyte ,uint8_t *rbyte)
{
	if(DRV_SPI2 == spi_id)
	{
		SPI_SET_SS_LOW(SPI2);
		SPI_WRITE_TX(SPI2, wbyte);
		while(SPI_IS_BUSY(SPI2));
		*rbyte = SPI_READ_RX(SPI2);
		SPI_SET_SS_HIGH(SPI2);
	}
	return TRUE;
}

uint8_t drv_spi_write_byte(uint8_t spi_id ,uint8_t wr_byte)
{
	uint16_t i = 0;
	SPI_SET_SS_LOW(SPI2);

	if(!SPI_GET_TX_FIFO_FULL_FLAG(SPI2))
    {
            SPI_WRITE_TX(SPI2, wr_byte);
	}
	while(SPI_IS_BUSY(SPI2));
	SPI_SET_SS_HIGH(SPI2);
	SPI_ClearRxFIFO(SPI2);
	
	return TRUE;
}

uint8_t drv_spi_write_data(uint8_t spi_id ,uint8_t *wr_buf , uint16_t wr_num)
{
	uint16_t i = 0;
	SPI_SET_SS_LOW(SPI2);
	for( i = 0;i < wr_num; ++ i)
	{
		if(!SPI_GET_TX_FIFO_FULL_FLAG(SPI2))
        {
            SPI_WRITE_TX(SPI2, wr_buf[i]);
        }
	}
	while(SPI_IS_BUSY(SPI2));
	SPI_SET_SS_HIGH(SPI2);
	SPI_ClearRxFIFO(SPI2);
	
	return TRUE;
}

uint8_t drv_spi_read_data(uint8_t spi_id ,uint8_t *rd_buf , uint16_t rd_num)
{
	uint16_t i = 0;
	if(DRV_SPI2 == spi_id)
	{
		SPI_SET_SS_LOW(SPI2);
		for(i = 0;i < rd_num; ++ i)
		{
			SPI_WRITE_TX(SPI2, 0x00);
			while(SPI_IS_BUSY(SPI2));
			*rd_buf = SPI_READ_RX(SPI2);
		}
		while(SPI_IS_BUSY(SPI2));
		SPI_SET_SS_HIGH(SPI2);
	}
}

/**
 * @brief  SPI读写多个字节
 * @param  spi_id : SPI 接口
 * @param  wbuf : 写缓冲区
 * @param  rbuf : 读缓冲区
 * @param  size : 读写长度
 * @return void 
 */
uint8_t drv_spi_write_read_data(uint8_t spi_id , uint8_t *wbuf ,uint8_t *rbuf ,uint32_t size)
{
	uint32_t i = 0;
	
	SPI_SET_SS_LOW(SPI2);
	
	for( i = 0;i < size; ++ i)
	{
        SPI_WRITE_TX(SPI2, wbuf[i]);
		while(SPI_IS_BUSY(SPI2));
		rbuf[i] = SPI_READ_RX(SPI2);
	}
	
	while(SPI_IS_BUSY(SPI2));
	
	SPI_SET_SS_HIGH(SPI2);

	return TRUE;
}

void drv_spi_soft_send_recv_bytes(uint8_t *send_buff, uint8_t *recv_buff, uint16_t data_size)
{
	uint16_t i = 0;
	for(i = 0;i < data_size; ++ i)
	{
		recv_buff[i] = drv_spi_soft_send_read_byte(send_buff[i]);
	}
}

void drv_spi_soft_send_bytes(uint8_t *send_buff, uint16_t data_size)
{
	uint16_t i = 0;
	for( i = 0;i < data_size; ++ i)
	{
		drv_spi_soft_send_byte(send_buff[i]);
	}
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static void drv_spi_soft_send_byte(uint8_t byte)
{
	uint8_t i = 0;
	spi_delay();
	for( i = 0;i < 8; ++ i)
	{
		drv_spi_clk_set_high();
		
		if(byte & 0x80)
			drv_spi_mosi_set_high();
		else
			drv_spi_mosi_set_low();
		
		byte <<= 1;
		
		drv_spi_clk_set_low();
	}
	
	drv_spi_mosi_set_low();
}

static uint8_t drv_spi_soft_send_read_byte(uint8_t s_byte)
{
	uint8_t i = 0;
	uint8_t read_byte = 0;
	spi_delay();
	
	for( i = 0;i < 8; ++ i)
	{
		drv_spi_clk_set_high();
		
		if(s_byte & 0x80)
			drv_spi_mosi_set_high();
		else
			drv_spi_mosi_set_low();
		
		s_byte <<= 1;

		drv_spi_clk_set_low();
		
		read_byte <<= 1;
		
		if(drv_spi_miso_read())
			read_byte |= 0x01;
	}	
	
	drv_spi_mosi_set_low();
	
	return read_byte;
}
/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/
